package com.biscuit.page.basicservice.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.biscuit.common.base.*;
import com.biscuit.page.basicservice.api.model.request.chat.*;
import com.biscuit.page.basicservice.api.model.response.chat.ChatRoomInfoAResp;
import com.biscuit.page.basicservice.api.model.response.chat.ChatRoomMessageAResp;
import com.biscuit.page.basicservice.conf.handler.RequestContextHandler;
import com.biscuit.page.basicservice.conf.handler.UserContextHandler;
import com.biscuit.page.basicservice.model.entities.mysql.SysChatRoom;
import com.biscuit.page.basicservice.model.entities.mysql.SysChatRoomMessage;
import com.biscuit.page.basicservice.model.entities.mysql.SysUser;
import com.biscuit.page.basicservice.model.entities.mysql.SysUserDetail;
import com.biscuit.page.basicservice.persistence.dao.ChatRoomDao;
import com.biscuit.page.basicservice.persistence.dao.ChatRoomMessageDao;
import com.biscuit.page.basicservice.persistence.dao.UserDao;
import com.biscuit.page.basicservice.utils.BaseExceptionUtil;
import com.biscuit.page.basicservice.utils.BaseResponseUtil;
import com.biscuit.page.basicservice.utils.BaseThreadUtil;
import com.biscuit.page.basicservice.utils.BaseVerifyUtil;
import com.biscuit.page.basicservice.websocket.MessageCallbackTypeEnum;
import com.biscuit.page.basicservice.websocket.chat_room.ChatRoomWebSocketContext;
import com.biscuit.page.basicservice.websocket.chat_room.ChatRoomWebSocketHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author biscuit
 * @createTime 2024/6/11 9:24
 */
@Slf4j
@Service
public class ChatService {

    @Resource
    private UserDao userDao;

    @Resource
    private ChatRoomDao chatRoomDao;

    @Resource
    private ChatRoomMessageDao chatRoomMessageDao;

    public BaseResponse<BaseResponseVoid> initAfter(Long chatRoomId) {
        // 获取当前用户的Uid
        String userUid = UserContextHandler.getUserUid();

        // 获取当前登录用户信息
        SysUser sysUser = UserContextHandler.getContext().getUser();

        // 获取当前登录用户详情信息
        SysUserDetail sysUserDetail = UserContextHandler.getContext().getUserDetail();

        // 获取在线信息上下文对象
        ChatRoomWebSocketContext context = ChatRoomWebSocketHandler.getContext(chatRoomId, userUid);

        // 完善在线用户上下文对象
        context.setSysUser(sysUser);
        context.setSysUserDetail(sysUserDetail);

        // 获取本次请求ip
        String ip = RequestContextHandler.getContext().getIp();

        // todo 异步日志记录

        // 新用户连接，异步向客户端发送消息，刷新实时在新用户信息
        BaseThreadUtil.async(() -> {
            // 获取指定聊天室下的所有用户在线上下文对象
            Map<String, ChatRoomWebSocketContext> contextMap = ChatRoomWebSocketHandler.getContextMap(chatRoomId);

            // 过滤本次连接的用户
            contextMap.keySet().stream().filter(x -> !x.equals(userUid)).forEach(x -> {
                try {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("type", MessageCallbackTypeEnum.REFRESH_ONLINE_LIST.getType());
                    ChatRoomWebSocketContext socketContext = contextMap.get(x);
                    socketContext.getSession().getBasicRemote()
                            .sendText(jsonObject.toJSONString());
                } catch (Exception e) {
                    log.error("ChatRoomWebSocketServer connect error -> {}", e.getMessage());
                }
            });
        });
        return BaseResponseUtil.success();
    }

    public BaseResponse<ChatRoomInfoAResp> getChatRoomInfo(Long chatRoomId) {
        // 根据 聊天室Id 查询聊天室详情信息
        SysChatRoom chatRoom = this.chatRoomDao.getById(chatRoomId);

        // 聊天室非空判断
        BaseExceptionUtil.throwException(
                Objects.nonNull(chatRoom) && BaseVerifyUtil.verifyDeletedValid(chatRoom.getIsDeleted()), "聊天室不存在"
        );

        // 状态判断
        BaseExceptionUtil.throwException(chatRoom.getStatus() == 1, "聊天室状态异常");

        // 转换为响应对象类型
        ChatRoomInfoAResp resp = new ChatRoomInfoAResp();
        resp.setChatRoomId(chatRoom.getId());
        resp.setChatRoomName(chatRoom.getName());
        resp.setUserId(chatRoom.getUserId());
        // todo 待优化为连表
        resp.setUserNickName(UserContextHandler.getContext().getUser().getNickName());
        resp.setChatRoomStatusValue("哈哈哈");
        resp.setChatRoomDescription(chatRoom.getDescription());


        return BaseResponseUtil.success(resp);
    }


    public BaseResponse<ChatRoomInfoAResp> saveChatRoom(ChatRoomNewCreateAReq req) {
        return null;
    }

    public BaseResponse<BasePageListResponse<ChatRoomMessageAResp>> pageMessageByChatRoomId(ChatRoomMessagePageAReq req) {
        // 分页数据检查
        req.check();

        // 查询指定聊天室的聊天消息
        List<ChatRoomMessageAResp> respList = Optional.of(this.chatRoomMessageDao.pageByChatRoomId(req)).orElse(new ArrayList<>());

        // 查询分页数据总条数
        int total = this.chatRoomMessageDao.pageTotalByChatRoomId(req);

        // 返回聊天室聊天消息
        BasePageListResponse<ChatRoomMessageAResp> response = new BasePageListResponse<>();
        response.setList(
                // 数据排序
                respList.stream()
                        .sorted(Comparator.comparing(ChatRoomMessageAResp::getPublishTime)).collect(Collectors.toList())
        );
        response.setPageNo(req.getPageNo());
        response.setPageSize(req.getPageSize());
        response.setTotal(total);
        return BaseResponseUtil.success(response);
    }

    public BaseResponse<BaseModelResponse<Long>> execBeforeMessagePublishToChatRoom(ChatRoomMessageSaveBeforeAReq req) {
        // 参数校验
        BaseExceptionUtil.throwException(BaseVerifyUtil.verifyNumberFullValid(req.getChatRoomId()), "聊天室ID为空");

        // 获取当前用户的Uid
        String userUid = UserContextHandler.getUserUid();

        // 获取当前用户的用户id
        Long userId = UserContextHandler.getUserId();

        // 预存储消息，并且获取自增消息Id
        SysChatRoomMessage data = new SysChatRoomMessage();
        data.setChatRoomId(req.getChatRoomId());
        data.setUserUid(userUid);
        data.setUserId(userId);
        this.chatRoomMessageDao.saveAndIncrement(data);

        // 返回消息的自增Id
        return BaseResponseUtil.success(new BaseModelResponse<>(data.getId()));
    }

    public BaseResponse<BaseModelResponse<Boolean>> saveMessageToChatRoom(ChatRoomMessageSaveAReq req) {
        // 参数校验
        BaseExceptionUtil.throwException(BaseVerifyUtil.verifyNumberFullValid(req.getMessageId()), "非法消息Id");
        BaseExceptionUtil.throwException(BaseVerifyUtil.verifyNumberFullValid(req.getChatRoomId()), "非法聊天室Id");
        req.setPublishTime(Objects.nonNull(req.getPublishTime()) ? req.getPublishTime() : LocalDateTime.now());

        // 修补预存储的消息
        this.chatRoomMessageDao.updateBeforeMessage(req);

        // 获取当前用户的Uid
        String userUid = UserContextHandler.getUserUid();

        // 获取用户信息
        SysUser sysUser = UserContextHandler.getContext().getUser();

        // 异步将新消息同步给指定聊天室下的所有在线用户
        BaseThreadUtil.async(() -> {
            ChatRoomWebSocketHandler.getContextMap(req.getChatRoomId()).keySet()
                    .stream().filter(x -> !x.equals(userUid))
                    .forEach(x -> {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("type", MessageCallbackTypeEnum.NEW_MESSAGE_INFORM.getType());
                        jsonObject.put("message", req.getMessageBody());
                        jsonObject.put("chatRoomId", req.getChatRoomId());
                        jsonObject.put("nickName", sysUser.getNickName());
                        jsonObject.put("avatar", sysUser.getAvatar());
                        jsonObject.put("userUid", userUid);
                        jsonObject.put("publishTime", req.getPublishTime());
                        ChatRoomWebSocketContext context = ChatRoomWebSocketHandler.getContext(req.getChatRoomId(), x);
                        try {
                            context.getSession().getBasicRemote()
                                    .sendText(jsonObject.toJSONString());
                        } catch (Exception e) {
                            log.error("saveMessageToChatRoom error -> {}", e.getMessage());
                        }
                    });
        });

        // todo 异步记录消息发布的日志

        return BaseResponseUtil.success(new BaseModelResponse<>(Boolean.TRUE));
    }

    public BaseResponse<BaseListResponse<ChatRoomOnlineAReq>> listOnline(Long chatRoomId) {
        // 获取当前用户的Uid
        String userUid = UserContextHandler.getUserUid();

        // 获取指定聊天室下的所有在线用户上下文对象集合
        Map<String, ChatRoomWebSocketContext> contextMap = ChatRoomWebSocketHandler.getContextMap(chatRoomId);

        BaseListResponse<ChatRoomOnlineAReq> responseList = new BaseListResponse<>();

        // 判空直接返回，避免空指针异常
        if (CollectionUtils.isEmpty(contextMap)) {
            return BaseResponseUtil.success(responseList);
        }

        // 过滤掉当前用户的在线信息，返回其他用户的在线信息
        responseList.setList(
                contextMap.values().stream()
                        .filter(x -> !x.getUserUid().equals(userUid))
                        .map(x -> {
                            ChatRoomOnlineAReq data = new ChatRoomOnlineAReq();
                            data.setUserUid(x.getUserUid());
                            data.setNickName(x.getSysUser().getNickName());
                            data.setUserId(x.getSysUser().getId());
                            return data;
                        }).collect(Collectors.toList())
        );

        return BaseResponseUtil.success(responseList);
    }

}
